package com.chuanke.ckfamily.service.common.impl;


import com.chuanke.ckfamily.dao.user.model.User;
import com.chuanke.ckfamily.service.common.CacheService;
import com.chuanke.ckfamily.service.common.TokenService;
import com.chuanke.ckfamily.service.common.model.UserToken;
import com.chuanke.ckfamily.service.user.UserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sun.rmi.server.UnicastServerRef;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by wangbin on 2017/7/20.
 */
@Service
public class TokenServiceImpl implements TokenService {

    private Logger logger = LoggerFactory.getLogger(TokenService.class);

    @Autowired
    private CacheService cacheService;

    @Autowired
    private UserService userService;

    @Override
    public String createToken(User user, boolean cacheOld, boolean update) throws Exception {
        UserToken userToken = new UserToken(user.getId());
        String oldLoginToken = user.getToken();
        if (cacheOld) {
            userToken.setOldToken(oldLoginToken);
        }

        RedisLockUtil lockUtil = cacheService.getLock(UserToken.KEY + user.getId());
        try {
            if (cacheOld && StringUtils.isNotEmpty(oldLoginToken)) {
                UserToken oldToken = getUserToken(oldLoginToken);
                if (oldToken != null) {
                    oldToken.setNewToken(userToken.getToken());
                    cacheService.set(UserToken.KEY + oldToken.getToken(), oldToken);
                }
            }
            cacheService.set(UserToken.KEY + userToken.getToken(), userToken);

        } catch (Exception e)  {
            e.printStackTrace();

        } finally {
            lockUtil.unlock();

        }

        if (update) {
            user = userService.findById(user.getId());

            User updateUser = new User();
            updateUser.setId(user.getId());
            updateUser.setToken(userToken.getToken());
            userService.update(updateUser);
        }

        return userToken.getToken();
    }

    @Override
    public Map<String, Object> createToken(UserToken oldToken, boolean update) throws Exception {
        UserToken userToken = new UserToken(oldToken.getId());

        RedisLockUtil lockUtil = cacheService.getLock(UserToken.KEY + oldToken.getId());
        try {
            userToken.setOldToken(oldToken.getToken());
            // 产生新的token 并且将过期的token放入新的里面
            cacheService.set(UserToken.KEY + userToken.getToken(), userToken);

            oldToken = getUserToken(oldToken.getToken());

            oldToken.setNewToken(userToken.getToken());
            // 将新的token放入到过期的token里面
            cacheService.set(UserToken.KEY + oldToken.getToken(), oldToken);

        } finally {
            lockUtil.unlock();

        }

        logger.debug("createToken========>user={} userToken={}",oldToken.getId(), userToken);
        if (update) {
            User user = userService.findById(userToken.getId());
            user.setToken(userToken.getToken());
            userService.update(user);
        }

        Map<String, Object> result = new HashMap<>(2);
        result.put("token", userToken.getToken());
        result.put("timeSpan", UserToken.TIME_SPAN - 60000);
        return result;
    }

    @Override
    public void cleanToken(UserToken token) throws Exception {
        UserToken oldToken = null;

        RedisLockUtil lockUtil = cacheService.getLock(UserToken.KEY + token.getId());
        try {
            cacheService.delete(UserToken.KEY + token.getToken());
            logger.debug("delete token ={} for uid={}", token.getToken(), token.getId());

            if (StringUtils.isNotEmpty(token.getNewToken())) {
            	// UserToken newToken = (UserToken)cacheService.get(UserToken.KEY + token.getNewToken());
                UserToken newToken = getUserToken(token.getNewToken());
                if (newToken != null) {
                    newToken.setOldToken(null);
                    cacheService.set(UserToken.KEY + newToken.getToken(), newToken);
                }
            }

            if (StringUtils.isNotEmpty(token.getOldToken())) {
                oldToken = getUserToken(token.getOldToken());
            }

        } finally {
            lockUtil.unlock();

        }

        if (oldToken != null) {
            cleanToken(oldToken);
        }
    }

    @Override
    public UserToken getUserToken(String token) {
    	UserToken userToken = (UserToken)cacheService.get(UserToken.KEY + token);
    	if (userToken == null) {
    	    User user = userService.findByToken(token);
    	    if (user != null) {
    	        userToken = new UserToken(user.getId(), token);
                cacheService.set(UserToken.KEY + token, userToken);
            }
        }

        return userToken;
    }
}